package com.redis.controller;

import org.redisson.api.*;
import org.redisson.api.listener.PatternMessageListener;
import org.redisson.client.protocol.pubsub.Message;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionStage;

/***
 * 程序接口调用方式
 * 异步执行方式
 *
 * 分布式对象
 */
@RestController
public class TestObjectController {

    @Resource
    private RedissonClient redissonClient;

    @RequestMapping(value = "/test")
    public void atomic() throws IOException {

        //所有与Redis key相关的操作都归纳在RKeys这个接口里：
        RKeys keys = redissonClient.getKeys();

        Iterable<String> allKeys = keys.getKeys();
        Iterable<String> foundedKeys = keys.getKeysByPattern("key*");
        long numOfDeletedKeys = keys.delete("obj1", "obj2", "obj3");
        long deletedKeysAmount = keys.deleteByPattern("test?");
        String randomKey = keys.randomKey();
        long keysAmount = keys.count();


        // 通用对象桶（Object Bucket）
        RBucket<Object> bucket = redissonClient.getBucket("anyObject");
        bucket.set(new Object());
        Object obj = bucket.get();

        bucket.trySet(new Object());
        bucket.compareAndSet(new Object(), new Object());
        bucket.getAndSet(new Object());



        // 二进制流（Binary Stream）
        RBinaryStream stream = redissonClient.getBinaryStream("anyStream");
        byte[] content = null;
        stream.set(content);

        InputStream is = stream.getInputStream();
        byte[] readBuffer = new byte[512];
        is.read(readBuffer);

        //地理空间对象桶（Geospatial Bucket）
        RGeo<String> geo = redissonClient.getGeo("test");
        geo.add(new GeoEntry(13.361389, 38.115556, "Palermo"),
                new GeoEntry(15.087269, 37.502669, "Catania"));
        geo.addAsync(37.618423, 55.751244, "Moscow");

        Double distance = geo.dist("Palermo", "Catania", GeoUnit.METERS);
        geo.hashAsync("Palermo", "Catania");
        Map<String, GeoPosition> positions = geo.pos("test2", "Palermo", "test3", "Catania", "test1");
        List<String> cities = geo.radius(15, 37, 200, GeoUnit.KILOMETERS);
        Map<String, GeoPosition> citiesWithPositions = geo.radiusWithPosition(15, 37, 200, GeoUnit.KILOMETERS);


        //BitSet
        // Redisson的分布式RBitSetJava对象采用了与java.util.BiteSet类似结构的设计风格。
        // 可以理解为它是一个分布式的可伸缩式位向量。需要注意的是RBitSet的大小受Redis限制，
        // 最大长度为4 294 967 295。
        RBitSet set = redissonClient.getBitSet("simpleBitset");
        set.set(0, true);
        set.set(1812, false);
        set.clear(0);
        set.andAsync("e");
        set.xor("anotherBitset");


        //BitSet数据分片（Sharding）（分布式RoaringBitMap）
        //基于Redis的Redisson集群分布式BitSet通过RClusteredBitSet接口，
        // 为集群状态下的Redis环境提供了BitSet数据分片的功能。通过优化
        // 后更加有效的分布式RoaringBitMap算法，突破了原有的BitSet大小限制，
        // 达到了集群物理内存容量大小。在这里可以获取更多的内部信息。
//        RClusteredBitSet set = redisson.getClusteredBitSet("simpleBitset");
//        set.set(0, true);
//        set.set(1812, false);
//        set.clear(0);
//        set.addAsync("e");
//        set.xor("anotherBitset");


        //原子整长形（AtomicLong）
        //Redisson的分布式整长形RAtomicLong对象和Java中的java.util.concurrent.atomic.AtomicLong对象类似。


        RAtomicLong atomicLong = redissonClient.getAtomicLong("myAtomicLong");
        atomicLong.set(3);
        atomicLong.incrementAndGet();
        atomicLong.get();



        //原子双精度浮点（AtomicDouble）
        //Redisson还提供了分布式原子双精度浮点RAtomicDouble，弥补了Java自身的不足。

        RAtomicDouble atomicDouble = redissonClient.getAtomicDouble("myAtomicDouble");
        atomicDouble.set(2.81);
        atomicDouble.addAndGet(4.11);
        atomicDouble.get();

        //话题（订阅分发）
        //Redisson的分布式话题RTopic对象实现了发布、订阅的机制。

        /**
         *
         RTopic<SomeObject> topic = redisson.getTopic("anyTopic");
        topic.addListener(new MessageListener<SomeObject>() {
            @Override
            public void onMessage(String channel, SomeObject message) {
                //...
            }
        });

        // 在其他线程或JVM节点
        RTopic<SomeObject> topic = redisson.getTopic("anyTopic");
        long clientsReceivedMessage = topic.publish(new SomeObject());

         */

        RTopic<String> topic = redissonClient.getTopic("anyTopic");
        long clientsReceivedMessage = topic.publish(new String("1111111111111111111"));

        System.out.println(clientsReceivedMessage);


        //模糊话题
        //Redisson的模糊话题RPatternTopic对象可以通过正式表达式来订阅多个话题。

        // 订阅所有满足`topic1.*`表达式的话题
        /*RPatternTopic<Message> topic1 = redissonClient.getPatternTopic("topic1.*");
        int listenerId = topic1.addListener(new PatternMessageListener<Message>() {
            @Override
            public void onMessage(CharSequence pattern, CharSequence channel, Message msg) {

            }
        });*/

        //布隆过滤器（Bloom Filter）
        //Redisson利用Redis实现了Java分布式布隆过滤器（Bloom Filter）。所含最大比特数量为2^32

        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("sample");
// 初始化布隆过滤器，预计统计元素数量为55000000，期望误差率为0.03
        bloomFilter.tryInit(55000000L, 0.03);
//        bloomFilter.add(new SomeObject("field1Value", "field2Value"));
//        bloomFilter.add(new SomeObject("field5Value", "field8Value"));
//        bloomFilter.contains(new SomeObject("field1Value", "field8Value"));



//        基数估计算法（HyperLogLog）
//        Redisson利用Redis实现了Java分布式基数估计算法（HyperLogLog）对象。

        RHyperLogLog<Integer> log = redissonClient.getHyperLogLog("log");
        log.add(1);
        log.add(2);
        log.add(3);
        log.add(3);
        log.add(3);
        log.add(3);

        log.count();


//        整长型累加器（LongAdder）
//        基于Redis的Redisson分布式整长型累加器采用了与java.util.concurrent.atomic.LongAdder类似的接口。通过利用客户端内置的LongAdder对象，为分布式环境下递增和递减操作提供了很高得性能。据统计其性能最高比分布式AtomicLong对象快 12000 倍。完美适用于分布式统计计量场景。

        RLongAdder atomicLonga = redissonClient.getLongAdder("myLongAdder");
        atomicLonga.add(12);
        atomicLonga.increment();
        atomicLonga.decrement();
        atomicLonga.sum();

        atomicLonga.destroy();


//        双精度浮点累加器（DoubleAdder）
//        基于Redis的Redisson分布式双精度浮点累加器采用了与java.util.concurrent.atomic.DoubleAdder类似的接口。通过利用客户端内置的DoubleAdder对象，为分布式环境下递增和递减操作提供了很高得性能。据统计其性能最高比分布式AtomicDouble对象快 12000 倍。完美适用于分布式统计计量场景。

//        RLongDouble atomicDouble = redissonClient.getLongDouble("myLongDouble");
//        atomicDouble.add(12);
//        atomicDouble.increment();
//        atomicDouble.decrement();
//        atomicDouble.sum();


    }

}
